package edg.db;

import java.sql.*;

public class StatCalculator
{
    
     /**
     * Calculate ER Statistics.  Stores to database the calculated results.
     * 
     * @param runID
     *            The run statistics are being calculated for.
     */
    
    public static void Calculate(int runID)
    {
        
        // these variables will store first the total hours all the faculty
        // worked then the total faculty
        float[] doctors = utilStats(runID, "doctor");
        float[] nurses = utilStats(runID, "nurse");
        float[] triage = utilStats(runID, "triage");
        float[] clerks = utilStats(runID, "clerk");
        float[] beds = utilStats(runID, "bed");
        
        // These are the variables that will be stored in the database, they are
        // the distribution of time based on acuity
        
        float[] acquity1 = patientStats(runID, 1);
        float[] acquity2 = patientStats(runID, 2);
        float[] acquity3 = patientStats(runID, 3);
        float[] acquity4 = patientStats(runID, 4);
        float[] acquity5 = patientStats(runID, 5);
        float[] acquity6 = patientStats(runID, 6);
        
        // These are more variable that will be stored in the database, they are
        // the distribution based on all acuities at the select step of the
        // simulator
        float[] patientTriage = stepStats(runID, "waiting_room_los");
        float[] patientTreatment = stepStats(runID, "inside_ed_los");
        
        // This will insert the Calculated results into the database
        Database
                .query(

                "INSERT "
                        + "INTO runs_summary (id, triage_00, triage_25, triage_50, triage_75, triage_95, triage_100, treatment_00, treatment_25, treatment_50, treatment_75, treatment_95, treatment_100, acuity1_00, acuity1_25, acuity1_50, acuity1_75, acuity1_95, acuity1_100, acuity2_00, acuity2_25, acuity2_50, acuity2_75, acuity2_95, acuity2_100, acuity3_00, acuity3_25, acuity3_50, acuity3_75, acuity3_95, acuity3_100, acuity4_00, acuity4_25, acuity4_50, acuity4_75, acuity4_95, acuity4_100, acuity5_00, acuity5_25, acuity5_50, acuity5_75, acuity5_95, acuity5_100, acuity6_00, acuity6_25, acuity6_50, acuity6_75, acuity6_95, acuity6_100, util_doctors_00, util_doctors_25, util_doctors_50, util_doctors_75, util_doctors_95, util_doctors_100, util_nurses_00, util_nurses_25, util_nurses_50, util_nurses_75, util_nurses_95, util_nurses_100, util_triage_nurses_00, util_triage_nurses_25, util_triage_nurses_50, util_triage_nurses_75, util_triage_nurses_95, util_triage_nurses_100, util_clerks_00, util_clerks_25, util_clerks_50, util_clerks_75, util_clerks_95, util_clerks_100, util_beds_00, util_beds_25, util_beds_50, util_beds_75, util_beds_95, util_beds_100) "
                        + "VALUES(" + runID + ", '"
                        + patientTriage[0]
                        + "', '"
                        + patientTriage[1]
                        + "', '"
                        + patientTriage[2]
                        + "', '"
                        + patientTriage[3]
                        + "', '"
                        + patientTriage[4]
                        + "', '"
                        + patientTriage[5]
                        + "', '"
                        + patientTreatment[0]
                        + "', '"
                        + patientTreatment[1]
                        + "', '"
                        + patientTreatment[2]
                        + "', '"
                        + patientTreatment[3]
                        + "', '"
                        + patientTreatment[4]
                        + "', '"
                        + patientTreatment[5]
                        + "', '"
                        + acquity1[0]
                        + "', '"
                        + acquity1[1]
                        + "', '"
                        + acquity1[2]
                        + "', '"
                        + acquity1[3]
                        + "', '"
                        + acquity1[4]
                        + "', '"
                        + acquity1[5]
                        + "', '"
                        + acquity2[0]
                        + "', '"
                        + acquity2[1]
                        + "', '"
                        + acquity2[2]
                        + "', '"
                        + acquity2[3]
                        + "', '"
                        + acquity2[4]
                        + "', '"
                        + acquity2[5]
                        + "', '"
                        + acquity3[0]
                        + "', '"
                        + acquity3[1]
                        + "', '"
                        + acquity3[2]
                        + "', '"
                        + acquity3[3]
                        + "', '"
                        + acquity3[4]
                        + "', '"
                        + acquity3[5]
                        + "', '"
                        + acquity4[0]
                        + "', '"
                        + acquity4[1]
                        + "', '"
                        + acquity4[2]
                        + "', '"
                        + acquity4[3]
                        + "', '"
                        + acquity4[4]
                        + "', '"
                        + acquity4[5]
                        + "', '"
                        + acquity5[0]
                        + "', '"
                        + acquity5[1]
                        + "', '"
                        + acquity5[2]
                        + "', '"
                        + acquity5[3]
                        + "', '"
                        + acquity5[4]
                        + "', '"
                        + acquity5[5]
                        + "', '"
                        + acquity6[0]
                        + "', '"
                        + acquity6[1]
                        + "', '"
                        + acquity6[2]
                        + "', '"
                        + acquity6[3]
                        + "', '"
                        + acquity6[4]
                        + "', '"
                        + acquity6[5]
                        + "', '"
                        + doctors[0]
                        + "', '"
                        + doctors[1]
                        + "', '"
                        + doctors[2]
                        + "', '"
                        + doctors[3]
                        + "', '"
                        + doctors[4]
                        + "', '"
                        + doctors[5]
                        + "', '"
                        + nurses[0]
                        + "', '"
                        + nurses[1]
                        + "', '"
                        + nurses[2]
                        + "', '"
                        + nurses[3]
                        + "', '"
                        + nurses[4]
                        + "', '"
                        + nurses[5]
                        + "', '"
                        + triage[0]
                        + "', '"
                        + triage[1]
                        + "', '"
                        + triage[2]
                        + "', '"
                        + triage[3]
                        + "', '"
                        + triage[4]
                        + "', '"
                        + triage[5]
                        + "', '"
                        + clerks[0]
                        + "', '"
                        + clerks[1]
                        + "', '"
                        + clerks[2]
                        + "', '"
                        + clerks[3]
                        + "', '"
                        + clerks[4]
                        + "', '"
                        + clerks[5]
                        + "', '"
                        + beds[0]
                        + "', '"
                        + beds[1]
                        + "', '"
                        + beds[2]
                        + "', '"
                        + beds[3]
                        + "', '" + beds[4] + "', '" + beds[5] + "');"

                );
    }
    
    // During Demo Day this function will be disabled to show that the
    // intermediate data actually existed
    // Database.query(
    //			
    // "Delete " +
    // "FROM simrunevents " +
    // "WHERE user = user AND runID == runID;"
    //			
    // );
    
    /**
	 * Helper method to get result set size.
	 * @param s object that you want to know the size of.
	 * @return Size of the result set.
	 */
    public static int getResultSetSize(ResultSet s)
    {
        int pos = 0;
        int res = 0;
        try
        {
            // pos = s.getRow();
            s.last();
            res = s.getRow();
            s.first();
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return res;
    }
    
    /**
     * Calculate the resource utilization for a given type.
     * @param run Run ID of the current run.
     * @param resourceType Resource type you are calculating statistics for.
     * @return Spread of utilization for given resource type.
     */
    public static float[] utilStats(int run, String resourceType)
    {
        
        // retrieves all patients of a certain acuity
        Statement typeData = Database.query(

        "SELECT utilization " + "FROM runs_resources " + "WHERE type = '"
                + resourceType + "' AND run_id = " + run + " "
                + "ORDER BY utilization ASC;"

        );
        
        // creates the array that will be returned
        float[] typeDistribution =
        { 0, 0, 0, 0, 0, 0 };
        int tot = 0;
        try
        {
            tot = getResultSetSize(typeData.getResultSet());
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        // iterates through the list storing the patients at predesignated
        // intervals
        try
        {
            
            ResultSet rs = typeData.getResultSet();
            state_loop: for (int i = 0; i < tot; i++)
            {
                if (i == 0)
                {
                    
                    typeDistribution[0] = rs.getFloat("utilization");
                }
                if (i == (int) Math.floor((tot * .25)))
                {
                    typeDistribution[1] = rs.getFloat("utilization");
                }
                if (i == (int) Math.floor((tot * .50)))
                {
                    typeDistribution[2] = rs.getFloat("utilization");
                }
                if (i == (int) Math.floor((tot * .75)))
                {
                    typeDistribution[3] = rs.getFloat("utilization");
                }
                if (i == (int) Math.floor((tot * .90)))
                {
                    typeDistribution[4] = rs.getFloat("utilization");
                }
                if (i == (int) Math.floor((tot - 1)))
                {
                    typeDistribution[5] = rs.getFloat("utilization");
                }
                if (rs.isLast())
                {
                    break state_loop;
                }
                rs.next();
            }
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
        
        return typeDistribution;
    }
    
    /**
     * Calculate patient Statistics.
     * 
     * @param run
     *            The run statistics are being calculated for.
     * @param acquity
     *            The acquity of patients the statistics are being calculated
     *            for
     * @return Returns a distribution of times in an array ranging from shortest
     *         patient time to longest for a patient acquity.
     */
    
    public static float[] patientStats(int run, int acquity)
    {
        
        // retrieves all patients of a certain acuity
        Statement patientData = Database.query(

        "SELECT waiting_room_los, inside_ed_los " + "FROM runs_patients "
                + "WHERE acuity = " + acquity + " AND run_id = " + run + " "
                + "ORDER BY waiting_room_los+inside_ed_los ASC;"

        );
        
        // creates the array that will be returned
        float[] patientDistribution =
        { 0, 0, 0, 0, 0, 0 };
        int tot = 0;
        try
        {
            tot = getResultSetSize(patientData.getResultSet());
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        // iterates through the list storing the patients at predesignated
        // intervals
        try
        {
            
            ResultSet rs = patientData.getResultSet();
            state_loop: for (int i = 0; i < tot; i++)
            {
                if (i == 0)
                {
                    
                    patientDistribution[0] = rs.getFloat("waiting_room_los")
                            + rs.getFloat("inside_ed_los");
                }
                if (i == (int) Math.floor((tot * .25)))
                {
                    patientDistribution[1] = rs.getFloat("waiting_room_los")
                            + rs.getFloat("inside_ed_los");
                }
                if (i == (int) Math.floor((tot * .50)))
                {
                    patientDistribution[2] = rs.getFloat("waiting_room_los")
                            + rs.getFloat("inside_ed_los");
                }
                if (i == (int) Math.floor((tot * .75)))
                {
                    patientDistribution[3] = rs.getFloat("waiting_room_los")
                            + rs.getFloat("inside_ed_los");
                }
                if (i == (int) Math.floor((tot * .90)))
                {
                    patientDistribution[4] = rs.getFloat("waiting_room_los")
                            + rs.getFloat("inside_ed_los");
                }
                if (i == (int) Math.floor((tot - 1)))
                {
                    patientDistribution[5] = rs.getFloat("waiting_room_los")
                            + rs.getFloat("inside_ed_los");
                }
                if (rs.isLast())
                {
                    break state_loop;
                }
                rs.next();
            }
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
        
        return patientDistribution;
    }
    
    /**
     * Calculate step Statistics.
     * 
     * @param run
     *            The run statistics are being calculated for.
     * @param step
     *            The step of the the statistics are being calculated for
     * @return Returns a distribution of times in an array ranging from shortest
     *         patient time to longest for a step, such as triage.
     */
    
    public static float[] stepStats(int run, String step)
    {
        
        // retrieves all the patients triage steps
        Statement stepData = Database.query(

        "SELECT " + step + " " + "FROM runs_patients " + "WHERE  run_id = "
                + run + " " + "ORDER BY " + step + " ASC;"

        );
        
        // initializes the array that is to be returned
        float[] stepDistribution =
        { 0, 0, 0, 0, 0, 0 };
        int tot = 0;
        try
        {
            tot = getResultSetSize(stepData.getResultSet());
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        // iterates through and assigned the patient's time at predesignated
        // intervals
        try
        {
            
            ResultSet rs = stepData.getResultSet();
            state_loop: for (int i = 0; i < tot; i++)
            {
                if (i == 0)
                {
                    
                    stepDistribution[0] = rs.getFloat(step);
                }
                if (i == (int) Math.floor((tot * .25)))
                {
                    stepDistribution[1] = rs.getFloat(step);
                }
                if (i == (int) Math.floor((tot * .50)))
                {
                    stepDistribution[2] = rs.getFloat(step);
                }
                if (i == (int) Math.floor((tot * .75)))
                {
                    stepDistribution[3] = rs.getFloat(step);
                }
                if (i == (int) Math.floor((tot * .90)))
                {
                    stepDistribution[4] = rs.getFloat(step);
                }
                if (i == (int) Math.floor((tot - 1)))
                {
                    stepDistribution[5] = rs.getFloat(step);
                }
                if (rs.isLast())
                {
                    break state_loop;
                }
                rs.next();
            }
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
        
        return stepDistribution;
    }
    
    /**
     * Return the results for a run.
     * 
     * @param RunID
     *            The run statistics are being calculated for.
     * @return Returns an array of strings that represent the results.
     */
    
}

